/**
 * ECP Web开发通用下拉选择控件.
 * Copyright(c) 2012-2020 YGSoft.Inc
 * @author zhengxianwei 
 * @date 2016-04-13
 */
define(["jquery","ecp.service","select2","ecp.utils","jstorage","ecp.const","ecp.utils.i18n"],function($,ecp,select2,utils,$jstorage,ecpConst,i18n){
	/**
	 * 默认参数.
	 */
	var defaultOptions = {
		multiple:false,
		isShowMore:false,
		allowClear:true,
		width: 150,
		pageSize:40,
		placeholder:i18n.select.selecting,
		containerCss: ''
	};
	var inheritMothd = ["getValue","getText","setValue","setParent","getPopState","setWidth","setHeight","value","initValue","getControl"];
	/**
	 * 声明ComboBox对象.
	 * @param {Object} origControl 控件的jQuery对象，即占位符。
	 * @param {option} option 控件的属性对象
	 */
	var ComboBox = function(origControl,option){
		if(arguments.length === 1){
			option = origControl;
			origControl = $("<div id='combobox"+Math.uuid()+"'>");
			this.origContainer = $("<div style='display:none;width:100%;'>");
			this.origContainer.append(origControl);
			$("body").append(this.origContainer);
		}
		if(!origControl || origControl.length === 0){return;}
        this.origControl = origControl;
		this.control = $("<div id='"+origControl.attr("id")+"_render' >");
        origControl.before(this.control);
        this.option = $.extend(true,{},defaultOptions,option);
        if(this.option.noWidth !== true){
        	var width = origControl.width();
            if(width){
            	this.option.width = width+10;
            }
        }else{
        	this.option.width = null;
        }
        //国际化处理
        var sel2 = this.control.select2;
        if(i18n.en_us){
        	//英文
        	$.extend(sel2.defaults,sel2.locales["en"]);
        }else if(i18n.zh_tw){
        	//繁体
        	$.extend(sel2.defaults,sel2.locales["zh-TW"]);
        }else{
        	//简体
        	$.extend(sel2.defaults,sel2.locales["zh-CN"]);
        }
        var ngModel = origControl.attr("ng-model");
        if(ngModel){
        	this.control.attr("ng-model",ngModel);
            origControl.removeAttr("ng-model");
        }
        //初始化
        this._init(this.control, option);
		//渲染控件
		this._render();
		//绑定事件
		this._bindEvent();
		
		return this;
	}
	/**
	 * 通过原型定义相关方法，比如渲染、赋值等等.
	 */
	ComboBox.prototype = {
			/**
	    	 * 初始化.
	    	 * 1、options数据来自参数和页面配置的data-option属性，以data-option为优先.
	    	 * 2、没有配置idField字段时取“id”，没有配置textField字段时取“text”.
	    	 * 3、配置了data属性则不需配置query函数.
	    	 * 4、将options缓存到dom对象上.
	    	 * @param {Object} control 控件的jQuery对象，即占位符。
	    	 * @param {Object} option 控件的属性对象
	    	 */
			_init: function(control, option){
				var dOpt = this.origControl.attr("data-option");
				if(dOpt && dOpt.length !== 0){
					dOpt = $.parseJSON(dOpt);
				}else{
					dOpt = {};
				}
				this.option = $.extend(true,{},this.option,dOpt);
				
				if(!this.option.idField){
					this.option.idField = "id";
				}
				if(!this.option.textField){
					this.option.textField = "text";
				}
				//如果没有传入数据则须绑定取数函数.
				var data = this.option.data;
				if (data == null) {
					this.option.query = $.proxy(this._queryData,this);
				}else{
					var idField = this.option.idField;
					var textField = this.option.textField;
					$.each(data,function(i,d){
						d.id = d[idField];
	        			d.text = d[textField];
					})
					this.option.data = data;
				}
				if(this.option.multiple){
					this.option.closeOnSelect = false;
					this.option.formatResult = this._formatResult;
					this.option.initSelection = this._initSelected;
	    		}
				this.control[0].option = this.option;
				this.control[0].ui = this;
			},
			
			/**
	    	 * 渲染下拉控件.
	    	 */
			_render: function(){
				this.control.attr("ecpclass",ecpConst.EcpClass.COMBOBOX);
				this.control.select2(this.option);
				this.origControl.hide();
				//add wugang
				//select2未对options.disabled处理
				if(this.option.disabled){
					this.disable();
				}
	    	},
	    	
	    	/**
	    	 * 将当前对象在表格中渲染需要实现的方法赋值给他们对象.
	    	 * 类似继承
	    	 * @param {Object} obj 控件对象
	    	 */
	    	inheritGridMethod: function(obj){
	    		if(!obj){return;}
	    		for(var i=0,len=inheritMothd.length; i<len; i++){
	    			obj[inheritMothd[i]] = this[inheritMothd[i]];
	    		}
	    		obj.control = this.control;
	    	},
	    	
	    	/**
	    	 * 获得当前控件对象对外公布的方法
	    	 */
	    	base: function(obj){
	    		if(!obj){return;}
	    		for(var method in this){
	    			if($.isFunction(this[method]) && method.substring(0,1) !== "_"){
	    				obj[method] = this[method];
	    			}
	    		}
	    		obj.control = this.control;
	    	},
	    	
	    	/**
	    	 * 格式处理.
	    	 * @param {Object} item 过滤项目
	    	 * @param {Object} container 容器
	    	 * @param {Object} query select2内置对象
	    	 * @return {Array} 数据数组
	    	 */
	    	 _formatResult:function(item, container, query){
	    		 var text = utils.escapeAngleBrackets(item.text);
	    		 container.attr("title",text);
	    		 var match=text.toUpperCase().indexOf(query.term.toUpperCase());
	             var len=query.term.length;
	             if (match<0) {
	            	 return   text;
	             }
	             var markup = [];
	             markup.push(text.substring(0, match));
	             markup.push("<span class='select2-match'>");
	             markup.push(text.substring(match, match + len));
	             markup.push("</span>");
	             markup.push(text.substring(match + len, text.length));
	             markup.push("</div>");
				return markup.join("");
	    	},
	
	    	/**
			 * 初始化选择对象.
			 */
			_initSelected: function(element, callback) {
				if(!this.element || this.element.length === 0){return;}
				var data = [];
				var selected = this.element[0].selected;
				for (var i in selected) {
					data.push(selected[i]);
				}
		        callback(data);
			},
			/**
	    	 * 获得服务.
	    	 * @param {Function} callback 回调
	    	 * @param {Object} option 控件的属性对象
	    	 * @param {Object} filter 过滤对象
	    	 */
	    	_getServer: function( callback,option,filter, isPageSize){
	    		if(!option){return;}
	    		var beanId = option.beanId,
	    			method = option.method,
	    			needContext = option.needContext,
	    			param = option.param;
	    		if(!beanId || !method){
	    			window.console.error(i18n.select.paramNotmatch);
	    			return;
	    		}
	    		if(!param){
					param = [];
				}
	    		var p = [];
	    		if(needContext !== false){
	    			p.push(ecp.DataContextUtil.getEcpDataContext());
	    		}
	    		if(isPageSize === true){
	    			p.push(filter);
	    		}
    			param = p.concat(param);
				//获取所有菜单
				ecp.RemoteService.doGetAsync(beanId,method,param,function(result){
					if(result.isSuccess()){
		            	callback(result.data);
					}else{
						window.console.error(i18n.select.listQueryError+": "+result.data);
					}
	    		});
	    	},
	    	
			/**
	    	 * 查询下拉列表数据.
	    	 * <p>
	    	 * 		控件默认取datas属性的数据作为下拉数据，如果不存在datas属性则调用dataSource属性获取下拉数据.
	    	 * </p>
	    	 * @param {Function} query 是select2内置的函数，用于设置下拉数据
	    	 * @return void
	    	 */
	    	_queryData: function(query){
	    		var me = this,
	    			opt = me.option,
	    			dataSource = opt.dataSource,
	    			callback = function(data){
		   				 if(!data){data=[];}
		   				 opt.serverData = data;
		   				 var idField = opt.idField;
		   				 var textField = opt.textField;
		   				 var disIds = me.disableIds;
		   				 //按照记忆的记录进行排序
	   					 data = me.getResultBySort(data);
		    			 $.each(data, function(i, d) {
		        			 d.id = d[idField];
		        			 d.text = d[textField];
		        			 if(!$.isEmptyObject(disIds) && disIds[d.id]){
		        				 d.disabled = disIds[d.id];
		        			 }
		        		 });
		    			 //处理可用
		   				 query.callback({results: data});
		   			};
	    		//下拉列表默认显示40条记录 
    			var filter = {
    				pageSize: opt.pageSize,
    				combobox: true,
    				text: query.term
    			}
    			if(opt.serverData && opt.noCache !== true){
    				callback(opt.serverData);
    			}else{
    				if($.isFunction(dataSource)){
    	    			dataSource.call(this,callback,opt,filter,me.control);
    	    		}else{
    	    			me._getServer(callback,opt,filter, true);
    	    		}
    			}
	    	},
	    	
	    	/**
	    	 * 加载列表数据.
	    	 * @param {Array} data 要设置的列表数据
	    	 */
	    	loadData: function(data){
	    		var opt = this.option;
	    		if(utils.notEmpty(data)){
	    			var idField = opt.idField;
	    			var textField = opt.textField;
	    			$.each(data, function(){
		    			this.id = this[idField];
		    			this.text = this[textField];
	    			})
	    			if(opt.data){
		    			opt.data = data;
		    		}else{
		    			opt.serverData = data;
		    		}
	    		}else{
	    			if(opt.data){
		    			opt.data = [];
		    		}else{
		    			opt.serverData = [];
		    		}	    			
	    		}
	    		this.value("");
	    		this._render();
				this._bindEvent();
	    		//this._modifyStyle();
	    	},
	    	
	    	/**
	    	 * 设置样式.
	    	 * @example 1
	    	 * comboBox.setStyle("backgroundColor","red");
	    	 * @example 2
	    	 * comboBox.setStyle({"backgroundColor":"red"});
	    	 * 
	    	 * @param {String | Object} styNm 为字符串时表示样式名，为object时是样式对象
	    	 * @param {String} val 样式的值
	    	 * 
	    	 */
	    	setStyle : function(styNm, val){
	    		if(!styNm){return;}
	    		var res = {};
	    		if(typeof styNm === "string"){
	    			res[styNm] = val;
	    		}else if(typeof styNm === "object"){
	    			res = styNm;
	    		}
	    		if(!$.isEmptyObject(res)){
	    			var container = this.control.select2("container");
	    			container.css(res);
	    			container.find("a.select2-choice").css(res);
	    			container.find("span.select2-arrow").css(res);
	    		}
	    	},
	    	
	    	/**
	    	 * 获取样式.
	    	 * @example
	    	 * comboBox.getStyle("backgroundColor");
	    	 * @param {String} styNm 为字符串时表示样式名
	    	 * @return val 样式的值
	    	 */
	    	getStyle : function(styNm){
	    		if(!styNm){return;}
	    		return this.control.select2("container").css(styNm);
	    	},
	    	
	    	/**
	    	 * 隐藏.
	    	 */
	    	hide: function(){
	    		this.control.select2("container").hide();
	    	},
	    	
	    	/**
	    	 * 显示.
	    	 */
	    	show: function(){
	    		this.control.select2("container").show();
	    	},
	    	
	    	/**
	    	 * 是否显示
	    	 */
	    	isShow: function(){
	    		 return this.control.select2("container").css("display") !== "none";
	    	},
	    	
	    	/**
			 * 可用
			 */
			enable: function(){
				this.control.select2("enable");
			},
			
			/**
			 * 不可用
			 */
			disable: function(){
				this.control.select2("disable");
			},
			
			/**
			 * 只读.
			 */
			readonly: function(){
				this.control.select2("readonly");
			},
			
	    	/**
	    	 * 通过项目对象可用
	    	 * @param {Array} items 数组
	    	 */
	    	eableByItems: function(items){
	    		this._disable(items,true,true);
	    	},
	    	
	    	/**
	    	 * 通过ID设置选项可用
	    	 * @param {Array} ids 数组
	    	 */
	    	eableByIds: function(ids){
	    		this._disable(ids,false,true);
	    	},
	    	
	    	/**
	    	 * 通过项目对象置灰(不可用)
	    	 * @param {Array} items
	    	 */
	    	disableByItems: function(items){
	    		this._disable(items,true,false);
	    	},
	    	
	    	/**
	    	 * 通过ID置灰(不可以)选项
	    	 * @param {Array} ids 数组
	    	 */
	    	disableByIds: function(ids){
	    		this._disable(ids,false,false);
	    	},
	    	
	    	/**
	    	 * 通过ID置灰选项，单选和多选
	    	 */
	    	_disable: function(ids,isItem,iseable){
	    		if(!ids || ids.length === 0){return;}
	    		var opt = this.option,
	    			idField = opt.idField,
	    			data = opt.data,
	    			idVal,_data,item,itemId,itemLen,flag;
	    		if(data){
	    			itemLen = ids.length;
    				for(var i=0,len=data.length; i<len; i++){
	    				_data = data[i];
	    				idVal = _data.id;
	    				idVal = idVal || _data[idField];
	    				flag = false;
    					for(var n=0,m=itemLen; n<m; n++){
    						//item
    						if(isItem){
    							item = ids[n];
		    					itemId = item.id;
		    					itemId =  itemId || item[idField];
    						}else{
    							//id
    							itemId = ids[n];
    						}
	    					if(itemId == idVal){
	    						flag = true;
	    						if(iseable === true){
	    							opt.data[i].disabled = false;
	    						}else{
	    							opt.data[i].disabled = true;
	    						}
		    					break;
	    					}
	    				}
    					//只匹配一个id或一个item时直接退出循环
    					if(flag && itemLen === 1){
    						break;
    					}
	    			}
	    		}else{
	    			if(!this.disableIds){
	    				this.disableIds = {};
	    			}
	    			for(var i=0,len=ids.length; i<len; i++){
	    				var id = ids[i];
	    				if(typeof (id) == "object"){
	    					id = id.id || id[idField];
	    				}
	    				this.disableIds[id+""] = iseable;
	    			}
	    		}
	    	},
	    	/**
	    	 * 设置控件的值.
	    	 * @param {String | Object} value
	    	 */
	    	setValue: function(value){
	    		this.value(value);
	    	},
	    	
	    	/**
	    	 * 获得控件的值.
	    	 * @return Array
	    	 */
	    	getValue: function(){
	    		var data = this.value(),id="";
	    		if(!data){return null;}
	    		if($.type(data) == "array"){
	    			for(var i=0,j=data.length; i<j; i++){
	    				id += "," + data[i].id;
	    			}
	    			if(id){
	    				id = id.substring(1);
	    			}
	    		}else{
	    			id = data.id;
	    		}
	    		return id;
	    	},
	    	
	    	/**
	    	 * 获得控件的显示值.
	    	 * @return Array
	    	 */
	    	getText: function(){
	    		var me = this,
	    			ct = me.control,
	    			res = "",
	    			val = ct.select2("val"),
	    			data = ct.select2("data");
	    		if(val == null || !data){return;}
	    		if(!me.option.multiple){
	    			data = [data];
	    			val = [val];
	    		}
	    		if(typeof(val) === "string"  && val.indexOf(",")){
	    			val = val.split(",");
	    		}
	    		for(var i=0,j=data.length; i<j; i++){
	    			if($.inArray(data[i].id+"",val) >= 0){
	    				res += ","+ data[i].text;
	    				continue;
	    			}
	    		}
	    		res = res && res.substring(1);
	    		return res;
	    	},
	    	
	    	/**
	    	 * 将渲染后的dom设置到指定的容器里面
	    	 * (如果要嵌入QzzGrid表格中则一定要实现该方法)
	    	 * @param container 容器
	    	 */
	    	setParent: function(container){
	    		container = $(container);
	    		if(!container || container.length === 0){return;}
	    		var ct = this.control,
	    			origCt = this.origControl,
	    			oc = this.origContainer;
	    		container.empty();
	    		$.each(oc.children(),function(){
	    			container.append(this);
	    		})
	    		container.append(oc.next());
	    		oc.remove();
	    	},
	    	
	    	/**
	    	 * 获得列表显示状态.
	    	 * (如果要嵌入QzzGrid表格中则一定要实现该方法)
	    	 * return true 下拉列表展开，false 下拉列表收缩.
	    	 */
	    	getPopState: function(){
	    		var ct = this.control;
	    		return (ct.select2('dropdown').css("display") !== "none") || (ct.attr("openWin") === "true");
	    	},
	    	
	    	/**
	    	 * 设置控件宽度.
	    	 */
	    	setWidth: function(width){
	    		if(width){
	    			width = parseFloat(width);
	    			this.getControl().prev().width(width);
	    		}
	    	},
	    	
	    	/**
	    	 * 设置控件高度.
	    	 */
	    	setHeight: function(height){
	    		if(height){
	    			height = parseFloat(height);
	    			this.getControl().prev().find("a.select2-choice").height(height);
	    		}
	    	},
	    	
			/**
			 * 设置和获取控件值.
			 * 不传参数则获取控件值，传参数表示设置控件值
			 * @param {String} value 即id值，可以是多个，用逗号分隔.
			 * @return {String | void} 获取值则返回字符串，设置值则返回空.
			 */
			value: function(value){
				 if(arguments.length === 0){
					 return this.control.select2("data");
				 }else{
					this.initValue(value);
				 }
			},
			 
			/**
			 * 初始化值.
			 * 1、参数是字符串类型，如果不存在属性data，那么就要用回调函数initDataFun查询ids对应的数据对象，并执行回调函数。
			 * 2、参数是数组类型，直接设置。
			 * @param {String | Array} value 即id值，可以是多个，字符串类型用逗号分隔，对象用数组存储.
			 * @return void
			 */
			initValue: function(value){
				if(!utils.notEmpty(value)){
					//清空值
					if(this.option.multiple){
						this.display(null);
					}else{
						this.control.select2("data",null);
					}
					return;
				 }
				 var type = $.type(value),
				 	 opt = this.option,
				 	 ct = this.control,
				 	 me = this,
					 datas = opt.data,
				  	 initDataFun = opt.initDataFun,
				 	 idField = opt.idField,
				  	 textField = opt.textField,
				  	 callback = function(data){
						 if(!data){return;}
						 for(var i=0,j=data.length; i<j; i++){
							 var d = data[i];
							 if(!d.id){
								 if(!utils.notEmpty(d[idField])){continue;}
								 data[i].id = d[idField];
							 }
							 if(!d.text){
								 data[i].text = d[textField] || "";
							 }
						 }
						 var orgData = ct.select2("data");
						 if(opt.multiple){
							 me.display(data);
							 //值发生变化时触发change事件
							 if($.isArray(orgData) && $.isArray(data)){
								 if(orgData.length !== data.length){
									 ct.trigger("change");
								 }else{
									 data = data.sort(function(a,b){
										 return a.id > b.id;
									 });
									 orgData = orgData.sort(function(a,b){
										 return a.id > b.id;
									 });
									 for(var i=0,len=data.length; i<len; i++){
										 if(data[i].id !== orgData[i].id){
											 ct.trigger("change");
											 break;
										 }
									 }
								 }
							 }
							 setTimeout(function(){
								 var $container = ct.select2("container");
								 var $ul = $container.find("ul.select2-choices");
								 $ul.parent().addClass("form-control select2 input_underline tip_required");
							 },0);
						 }else{
							 var res;
							 if($.type(data) == "array"){
								 res = data[0];
							 }else{
								 res = data;
							 }
							 ct.select2("data",res);
							//值发生变化时触发change事件
							 if(!orgData || (orgData && res && res.text !== orgData.text)){
								 ct.trigger("change");
							 }
						 }
					 };
				 if(type === "string" || type === "number"){
					 var values = (value + "").split(","),
					  	 ids = [];
					 $.each(values, function(i, v){
						 ids.push(v+"");
					 });
					 if(datas && datas.length !== 0){
						 var res = [],v;
						 $.each(datas,function(i,d){
							 v = d[idField];
							 if(typeof(v) === "number"){
								 v = v+"";
							 }
							 if($.inArray(v,ids)>-1){
								 res.push(d);
							 }
						 })
						 callback(res);
					 }else if($.isFunction(initDataFun)){
						 initDataFun.call(this,callback,ids,opt);
					 }
				 }else if(type === "object"){
					 var id = value.id;
					 var text = value.text;
					 if(!id && !text){return;}
					 id = "" + id;
					 if(id && id.indexOf(",") > -1 && text && text.indexOf(",") > -1){
						 id = id.split(",");
						 text = text.split(",");
						 var res = [];
						 for(var i=0,len=id.length; i<len; i++){
							 res.push({
								 id: id[i],
								 text: text[i]
							 });
						 }
						 callback(res);
					 }else{
						 callback(value);
					 }
				 }else if(type==="array"){
					 callback(value);
				 }
			},
			
			/**
			 * 显示值处理
			 */
			display: function(data){
				var ct = this.control;
				ct.parent().find(".selNumDiv").css("z-index", "999");
				ct.select2("data",data);
				//显示"已选择记录数"
				var container = ct.select2("container");
				if(container && container.length !== 0){
					 if(data && data.length !== 0){
						container.find("ul.select2-choices").find("li").hide();
						container.find(".selNumDiv").show();
						container.find("#selectNum").text(data.length);
					 }else{
						container.find("ul.select2-choices").find("li").show();
						container.find(".selNumDiv").hide();
					 }
				}
			},
			/**
			 * 获得控件的jquery对象.
			 * @return {Object}
			 */
			getControl: function(){
				return this.control;
			},
			
			/**
			 * 获得原始的jquery对象.
			 * @return {Object}
			 */
			getOrigControl: function(){
				return this.origControl;
			},
			
			/**
			 * 绑定事件
			 * @param {String} event 事件名.
			 * @param {Function} handler 函数
			 */
			bind: function(event,handler){
				this.control.bind(event,handler);
			},
			
			/**
			 * 解除绑定事件
			 * @param {String} event 事件名.
			 */
			unbind: function(event){
				this.control.unbind(event);
			},
			
			/**
			 * 绑定“更多”点击事件.
			 * @param {Function} handler 点击事件函数
			 */
			onClickMore: function(handler){
				this.option.clickMore = handler;
			},
			
			/**
			 * 设置存储本地KEY
			 * @param {String} key 存储的主键
			 */
			setStoreKey: function(key){
				if(utils.notEmpty(key)){
					this.option.storeKey = key;
				}
			},
			
			/**
			 * 获得焦点，显示下拉列表.
			 */
			focus: function(){
				var selCon = this.control.select2("container");
				if(selCon && selCon.length !== 0){
					selCon.find(".select2-choice").trigger("mousedown");
				}
			},
			
			/**
			 * 获得存储本地KEY
			 */
			getStoreKey: function(){
				return this.option.storeKey;
			},
			
			/**
			 * 设置记忆数据
			 * @param {String|Array} value 值，字符串时追加到已存在的数组中，数组时直接覆盖原来的历史数据
			 */
			setStoreHistory: function(value){
				var me = this,
					opt = me.option,
					storeKey = opt.storeKey;
				if(storeKey){
					var type = typeof (value),data=[];
					if(type === "string"){
						data = this.getStoreHistory();
						if(utils.notEmpty(data)){
							var vals = [value];
							if($.inArray(value,data) > -1){
								data.remove(value);
							}
							data = vals.concat(data);
							if(data.length > opt.pageSize){
								data.removeAt(data.length-1);
							}
						}else{
							data = [value];
						}
					}else if(type === "object"){
						data = value;
					}
					
					$.jStorage.set(storeKey,data);
				}
			},
			
			/**
			 * 获得记忆数据
			 */
			getStoreHistory: function(){
				var storeKey = this.option.storeKey;
				if(storeKey){
					return $.jStorage.get(storeKey);
				}
			},
			/**
			 * 通过记忆数据进行排序
			 * @param {Array} data数组
			 * @return {Array} 返回已排序的数组
			 */
			getResultBySort: function(data){
				var opt = this.option,
					storeKey = opt.storeKey,
					historyKey = opt.historyKey,
					historyData = this.getStoreHistory();
				if(!historyData && !storeKey && $.isFunction(historyKey)){
					historyData = historyKey.call(this,opt);
				}
				if(utils.notEmpty(historyData)){
					var sortData = [],
						otherData = [],
						dataObj = {},
						id = this.option.idField,
						len = historyData.length;
					$.each(data,function(j,d){
						if($.inArray(d[id], historyData) > -1){
							dataObj[d[id]] = d;
						}else{
							otherData.push(d);
						}
					})
					
					for(var i=historyData.length -1; i>=0; i--){
						var obj = dataObj[historyData[i]];
						if(obj){
							sortData.push(obj);
						}else{
							historyData.removeAt(i);
						}
					}
					//重新设置记忆数据
					if(len > historyData.length){
						this.setStoreHistory(historyData);
					}
					//倒序排列
					sortData = sortData.reverse();
					//排序和非排序数据组合
					sortData = sortData.concat(otherData);
					dataObj = null;
					return sortData;
				}else{
					return data;
				}
			},
			/**
			 * 事件绑定.
			 */
			_bindEvent: function(){
				this._bindSelectEvent();
				this._modifyStyle();
			},
			
			/**
	    	 * 修改原生样式.
	    	 */
	    	_modifyStyle: function(){
	    		var selCont = this.control.select2("container");
				if(!this.option.multiple){
	    			//处理单选样式
		    		var css = selCont.attr("class").replace("select2-container","select2-container form-control ");
		    		selCont.attr("class",css);
		    	} else {
					if(!selCont.hasClass("selNumDiv")){
						selCont.addClass("form-control select2");
		    			selCont.append('<div class="selNumDiv" style="position: absolute;display:none;height: 30px;line-height: 30px;right: 20px;left: 0;padding-left: 10px;font-size: 13px;">'+i18n.select.selected+' <font id="selectNum"></font> '+i18n.select.one+'</div>');
					}
		    	}
				//add by wugang 自定义容器样式
			   	if(this.option.containerCss){
		    		selCont.addClass(this.option.containerCss);
		    	}
				selCont.find(".select2-chosen").css({"white-space":"normal","word-break":"break-all"});
	    	},
			/**
			 * 绑定单选事件.
			 * afterDeleteEvent 删除后事件
			 */
			_bindSelectEvent: function(){
				var me = this,
					opt = me.option,
					control = me.control;
				//打开下拉事件
				control.unbind("select2-open").bind("select2-open", function(e) {
					//F1060224
					$(document).trigger("mousedown");
					
					//不管有没有数据，强制显示“更多”
					if(opt.forceShowMore){
						var dropdown = $(this).select2('dropdown');
						if(opt.isShowMore && dropdown.find('#addMore').length ==0){
							var detail = "<div style='padding-left:8px; height: 26px; line-height: 18px; margin-top: 1px;  text-indent: 5px;color: #333;background: #eeeeee;'>"
							+ "<a herf='#' style='float: right; margin-top: 4px; margin-right: 4px;'><span id='addMore' style='cursor:pointer' class='select2-arrow'>"+i18n.select.more+"</span></a></div>";
							dropdown.append(detail);
						}
						//更多点击事件.
	                    dropdown.find('.select2-arrow').unbind("click").bind("click",function(e){
	                    	me.option.clickMore && me.option.clickMore(me);
	                    	me.control.select2('close');
	                    });
					}
				})
				//加载事件
				control.unbind("select2-loaded").bind("select2-loaded", function(e) {
					var dropdown = $(this).select2('dropdown');
					//下拉位置调整。
					if(opt.multiple){
						var $choices = $(this).select2("container").find('.select2-choices'),
							top = dropdown.offset().top,
							cTop = $choices.offset().top,
							topOffset = top - cTop,
							height = $choices.height();
		    			if(topOffset > 0 && topOffset < 33){
		    				//兼容处理IE10及以上版本坐标
		    				if(utils.getIEVersion()>=10){
		    					top = top;
		    				}else{
		    					top = top + height;
		    				}
							dropdown.css("top", top +"px");
		    			} else {
		    				height = height - 34;
		    				dropdown.css("top", top + height + "px");
		    			}
					}
					//isShowMore是否显示更多
					if(opt.isShowMore && dropdown.find('#addMore').length ==0){
						var detail = "<div style='padding-left:8px; height: 26px; line-height: 18px; margin-top: 1px;  text-indent: 5px;color: #333;background: #eeeeee;'>"
						+ "<a herf='#' style='float: right; margin-top: 4px; margin-right: 4px;'><span id='addMore' style='cursor:pointer' class='select2-arrow'>"+i18n.select.more+"</span></a></div>";
						dropdown.append(detail);
					}
					var lis = dropdown.find("li"),optDiv;
					for(var i=0,len=lis.length; i<len; i++){
						optDiv = lis[i].children;
						$(optDiv).attr("title", $(optDiv).text());
					}
                    //更多点击事件.
                    dropdown.find('.select2-arrow').unbind("click").bind("click",function(e){
                    	me.option.clickMore && me.option.clickMore(me);
                    	me.control.select2('close');
						setTimeout(function(){
							var $container = control.select2("container");
							var $ul = $container.find("ul.select2-choices");
							$ul.parent().addClass("form-control select2 input_underline tip_required");
						},100);
                    });
				}); 
				//点击事件，记录已选择过的数据
				control.on("change", function(e) {
					var data = e.added;
					//设置记忆值
					if(utils.notEmpty(data)){
						me.setStoreHistory(data[opt.idField]);
					}
					if(!opt.multiple){
						//选择数据时给控件设置title
						var selChosen = control.select2("container").find(".select2-chosen");
						selChosen.attr("title", selChosen.text());
					}
				})
				//多选时，输入框显示选中的记录数
				if(opt.multiple){
					var resflag = false;
					var $container = control.select2("container");
					var $ul = $container.find("ul.select2-choices");
					var isEmptyItem = function(){
						return resflag === true || control.select2("data").length === 0;
					}
					var showOrHideLi = function(isShow){
						if(isShow === true){
							$ul.find("li").show();
							$ul.next().hide();
							$ul.parent().find(".selNumDiv").hide();
						}else{
							$ul.find("li").hide();
							if($ul.next().hasClass("selNumDiv")){
								$ul.next().show();
							}
							$ul.parent().find(".selNumDiv").show();
						}
					}
					var setSelNum = function(){
						$container.find("#selectNum").text(control.select2("data").length);
					}
					var origData;
					$container.on("mouseover", "ul,.selNumDiv", function(e){
						if(isEmptyItem())return;
						showOrHideLi(true);
						//绑定选择项的删除按钮事件
						$ul.find("a").unbind("click.multiple").bind("click.multiple",function(e){
							resflag = false;
							if($.isFunction(opt.afterDeleteEvent)){
								var newData = me.value(), res;
								if(newData && origData && origData.length !== 0){
									if(newData.length === 0){
										res = origData[0];
									}else{
										for(var i=0,len=origData.length; i<len; i++){
											var data = origData[i];
											var bool = false;
											for(var j=0,m=newData.length; j<m; j++){
												if(data.id == newData[j].id){
													bool = true; break;
												}
											}
											if(!bool){
												res = data; break;
											}
										}
									}
									opt.afterDeleteEvent.call(me,res,opt);
								}
							}
						}).unbind("mousedown.multiple").bind("mousedown.multiple",function(e){
							origData = me.value();
						})
						$ul.find("li").unbind("click.mulli").bind("click.mulli",function(){
							resflag = false;
						})
						$('ul.select2-choices', $container).css("z-index", "999");
					}).on("mouseout", "ul", function(e){
						if(isEmptyItem())return;
						showOrHideLi();
						//绑定选中条数面板mouseover事件
						$ul.next().off("mouseover").on("mouseover",function(){
							if(isEmptyItem())return;
							showOrHideLi(true);
						})
						setSelNum();
						$('ul.select2-choices', $container).css("z-index", "");
					}).on("mouseup", "ul", function(e){
						resflag = true;
						showOrHideLi(true);
						resflag = false;
					});
					control.bind("select2-close",function(e){
						resflag = false;
						//解决点击更多弹窗会把select2相关div的class丢失，这里补回去
						setTimeout(function(){
							$ul.parent().addClass("form-control select2 input_underline tip_required");
						},0);
						if(control.select2("data").length === 0)return;
						showOrHideLi();
						setSelNum();
						$('ul.select2-choices', $container).css("z-index", "");
					})
					control.bind("select2-open",function(e){
						resflag = true;
						showOrHideLi(true);
						$('ul.select2-choices', $container).css("z-index", "999");
					});
				}
			}
	};
	
	(function($) {
		var old = $.fn.comboBox;
		/**
		 * 集成到jquery中，暴露comboBox接口，渲染下拉控件
		 * @param {Object | String | Boolean} option
		 *  为object时表示渲染控件需要的参数;
		 *  为string时表示调用控件的方法；
		 *  为boolean时表示获取控件对象
		 */
		$.fn.comboBox = function(option){
			var me = this;
			if(!me || me.length === 0){
				if(window.console){
					window.console.error("ecp.component.comboBox"+i18n.select.renderError);
				}
				return;
			}
			option = option || {};
			var type = typeof(option);
			//如果第一个参数传入的是对象或空则初始化空件，如果传入的是字符串，则认为是调用里面的内部方法。
			if (type === "object") {
				var cbs = [];
				this.each(function() {
					var instanceOptions = $.extend({}, option, true);
					var instance = new ComboBox($(this), instanceOptions);
					this.comboBox = instance;
					cbs.push(instance);
				});
				if(cbs.length === 1){
					cbs = cbs[0];
				}
				return cbs;
			} else if (type === "string") {
				var args = Array.prototype.slice.call(arguments, 1);
				if (ComboBox.prototype[option]) {
					return ComboBox.prototype[option].call(args);
				} else {
					if ($.isEmptyObject(args)) {
						return this.select2(option);
					} else {
						return this.select2(option, args);
					}
				}
			} else if (option === true) {
				return me[0] && me[0].comboBox;
			}
		};
		$.fn.comboBox.Constructor = ComboBox;
		$.fn.comboBox.noConflict = function() {
			$.fn.comboBox = old;
			return this;
		};
	}(jQuery));
	return ComboBox;
});